#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

// 实现数据的序列化
bool Serialize(const Json::Value &val, std::string &body)
{
    std::stringstream ss;
    // StreamWriter是一个抽象类，不允许实例化对象
    // Json::StreamWriter writer;
    // 所以我们要使用工厂模式，实例化工厂类对象
    Json::StreamWriterBuilder swb;
    // 通过工厂类对象来生产派生类对象
    // Json::StreamWriter *sw = swb.newStreamWriter(); //父类指针指向子类
    std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());  // 使用智能指针避免内存泄漏
    int ret = sw->write(val, &ss);
    if(ret < 0)
    {
        std::cout << "Serialize fail" << std::endl;
        return false;
    }
    body = ss.str();
    return true;
    // delete sw;
}
//实现json字符串的反序列化
bool UnSerialize(std::string &body, Json::Value &val)
{
    // 定义工厂类对象
    Json::CharReaderBuilder crb;
    // 定义子类对象
    std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
    std::string errs;   // 错误原因
    bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
    if(ret == false)
    {
        std::cout << "UnSerialize fail" << errs << std::endl;
        return false;
    }
    return true;
}

int main()
{
    const char* name = "小明";
    int age = 18;
    const char* sex = "男";
    float score[3] = {88, 77.5, 67.3};
    // 定义一个value类对象
    Json::Value student;
    student["姓名"] = name;
    student["年龄"] = age;
    student["性别"] = sex;
    // 数组的添加是通过append来实现的
    student["分数"].append(score[0]);
    student["分数"].append(score[1]);
    student["分数"].append(score[2]);

    // Value 嵌套对象
    Json::Value fav;
    fav["书籍"] = "西游记";
    fav["运动"] = "打篮球";
    student["爱好"] = fav;

    std::string body;
    Serialize(student, body);
    std::cout << body << std::endl;

    Json::Value val;
    std::string str = body;
    UnSerialize(str, val);
    std::cout << "姓名: " << val["姓名"].asString() << std::endl;
    std::cout << "年龄: " << val["年龄"].asInt() << std::endl;
    std::cout << "性别: " << val["性别"].asString() << std::endl;
    int size = val["分数"].size();
    for(int i = 0; i < size;i++)
    {
        std::cout << "分数: " << val["分数"][i].asFloat() << std::endl;
    }
    return 0;
}